home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Utilities / Winter Shell 1.0d2 / Source / Libraries / FileLib / FileCopyLib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-08  |  4.1 KB  |  165 lines  |  [TEXT/KAHL]

  1. /*    Functions for copying files.
  2.  
  3.     93/12/02 aih
  4.     - removed calls to task library so i won't have to support them
  5.     
  6.     93/10/23 aih
  7.     - resource fork is copied only if it exists
  8.     
  9.     93/10/13 AIH
  10.     - Added calls to task library while copying files
  11.     - the file's catalog information is copied along with the file
  12.     
  13.     92/11/06 AIH
  14.     - Added FileReadNoError and FileCopyForkNoError to recover a file
  15.     on a floppy with a couple of damaged logical blocks
  16.     
  17.     91/05/17 AIH
  18.     - To allow the File Manager to automatically convert '\r' into '\n'
  19.     and vice versa when copying to or from an A/UX volume, the destination
  20.     file's creator and type are set immediately when it is created,
  21.     instead of after the copy (see TN229).
  22.     
  23.     91/05/06 Ari Halberstadt (AIH)
  24.     - Fixed mistake in FileCopyData (attempted to truncate the destination
  25.     file before the file had been opened).
  26.     - Fixed mistake in FileCopyFork (never noticed EOF) */
  27.     
  28. #include <limits.h>
  29. #include <string.h>
  30. #include "FileLib.h"
  31. #include "MathLib.h"
  32. #include "MemoryLib.h"
  33. #include "ResourceLib.h"
  34. #include "StringLib.h"
  35.  
  36. /* Files are stored in logical blocks of 512 bytes (IM-IV, 89).
  37.     When there's an error in a certain logical block, it's probably
  38.     necessary to skip that entire block. At least, that was my
  39.     experience with an I/O error on a floppy. */
  40. #define LOGICAL_BLOCK (512)
  41.  
  42. /* read a logical block from the file and ignore ioErr errors */
  43. static FilePosType FileReadNoError(FileType *fp, char buffer[LOGICAL_BLOCK])
  44. {
  45.     FilePosType startpos = 0;
  46.     FilePosType endpos = 0;
  47.     FilePosType count = 0;
  48.     volatile Boolean failed = false;
  49.     
  50.     TRY {
  51.         if (! failed) {
  52.             startpos = FilePosition(fp);
  53.             count = FileRead(fp, LOGICAL_BLOCK, buffer);
  54.         }
  55.         else {
  56.             /* Skip this damaged logical block. Replace unreadable bytes
  57.                 with nil bytes in the buffer. */
  58.             endpos = min(startpos + LOGICAL_BLOCK, FileSize(fp));
  59.             FileSeek(fp, fsFromStart, endpos);
  60.             memclr(buffer, LOGICAL_BLOCK);
  61.         }
  62.         ensure(FilePosition(fp) == min(startpos + LOGICAL_BLOCK, FileSize(fp)));
  63.     } CATCH {
  64.         if (FailReason() == ioErr) {
  65.             failed = true;
  66.             RETRY;
  67.         }
  68.     } ENDTRY;
  69.     return(count);
  70. }
  71.  
  72. /* copy either fork of a file, ignoring ioErr in source file (replaces
  73.     damaged blocks with nils) */
  74. static void FileCopyForkNoError(FileType *src, FileType *dst)
  75. {
  76.     FilePosType    count;
  77.     char buf[LOGICAL_BLOCK];
  78.     
  79.     do {
  80.         count = FileReadNoError(src, buf);
  81.         if (count > 0)
  82.             FileWrite(dst, count, buf);
  83.     } while (count > 0);
  84. }
  85.  
  86. /* copy either fork of a file */
  87. void FileCopyFork(FileType *src, FileType *dst)
  88. {
  89.     FilePosType    count = 0;
  90.     FilePosType bufsz = FILE_BUFSIZ;
  91.     volatile char smallbuf[FILE_BUFSIZ];
  92.     volatile char *buf = smallbuf;
  93.     
  94.     TRY {
  95.         if (MemAvailable(FileSize(src))) {
  96.             bufsz = FileSize(src);
  97.             buf = PtrBegin(bufsz);
  98.         }
  99.         do {
  100.             count = FileRead(src, bufsz, buf);
  101.             if (count > 0)
  102.                 FileWrite(dst, count, buf);
  103.         } while (count > 0);
  104.     } CLEANUP {
  105.         if (buf != smallbuf)
  106.             PtrEnd(buf);
  107.     } ENDTRY;
  108. }
  109.  
  110. /* Copy the data fork of the source file to the data fork of the
  111.     destination file. */
  112. void FileCopyData(FileType *src, FileType *dst)
  113. {
  114.     require(! FilesAreSame(src, dst));
  115.     TRY {
  116.         FileOpen(src, fsRdPerm);
  117.         FileOpen(dst, fsWrPerm);
  118.         FileResize(dst, 0);
  119.         FileCopyFork(src, dst);
  120.     } CLEANUP {
  121.         FileClose(src);
  122.         FileClose(dst);
  123.     } ENDTRY;
  124. }
  125.  
  126. /* Copy the resource fork of the source file to the resource fork of the
  127.     destination file. */
  128. void FileCopyRes(FileType *src, FileType *dst)
  129. {
  130.     require(! FilesAreSame(src, dst));
  131.     TRY {
  132.         FileOpenRes(src, fsRdPerm);
  133.         FileOpenRes(dst, fsWrPerm);
  134.         FileCopyFork(src, dst);
  135.     } CLEANUP {
  136.         FileClose(dst);
  137.         FileClose(src);
  138.     } ENDTRY;
  139. }
  140.  
  141. /* Copy both forks and the Finder and catalog information of the source
  142.     file to the destination file. */
  143. void FileCopy(FileType *src, FileType *dst)
  144. {
  145.     volatile Boolean created = false;
  146.     CInfoPBRec cat;
  147.     
  148.     TRY {
  149.         FileCatalog(src, &cat);
  150.         FileCreate(dst, cat.hFileInfo.ioFlFndrInfo.fdCreator,
  151.                              cat.hFileInfo.ioFlFndrInfo.fdType);
  152.         created = true;
  153.         FileCopyData(src, dst);
  154.         if (ResFileExists(src)) {
  155.             HCreateResFile(dst->vol, dst->dir, dst->pnm);
  156.             FailResError();
  157.             FileCopyRes(src, dst);
  158.         }
  159.         FileCatalogSet(dst, &cat);
  160.     } CATCH {
  161.         if (created)
  162.             FileDelete(dst);
  163.     } ENDTRY;
  164. }
  165.